import {isEmpty, isFunction, isString, omit, pick} from "lodash-es";
import FieldCtrl from "../Config/FieldCtrl";
import {Form, Col, Tooltip} from "antd";
import styles from "./index.module.less";
import React from "react";
import BaseComp from "./BaseComp";
import PropTypes from "prop-types";
import {ComponentType} from "../Config";
import endsWith from "lodash-es/endsWith";

/**
 * 表单基础组件的基类。与 BaseField 结合使用
 * 此组件是为了封装 Form.Item 的公共部分，以及表单基础组件的排版样式。
 */
export default class BaseFormItem extends BaseComp {

    static propTypes = {
        ...BaseComp.propTypes,
        formItemProps: PropTypes.object,
        compProps: PropTypes.object,
        // 标签文本的宽度
        labelWidth: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    };

    static defaultProps = {
        labelWidth: 77
    };

    /**
     * 组件的类
     * @type {BaseField | null}
     */
    Comp = null;

    /**
     * 组件的实例
     * @type { BaseField | null}
     */
    compIns = null;

    moreCommonProps() {
        return [...super.moreCommonProps(),
            'compLabel', 'fieldName', 'formItemProps', 'compProps', 'labelWidth'
        ]
    }

    initState(props) {
        return {
            formItemProps: {},
            compProps: {}
        }
    }

    componentDidMount() {
        super.componentDidMount();
        const {fieldName, appins, customprops, cell} = this.props;

        if (true !== cell && appins && fieldName && this.Comp && 'filter' !== this.Comp.fieldType) {
            // 此组件是作为应用的字段使用，则将组件的实例存到 appins.fieldInsObj 中，用于按需调用
            isFunction(appins.setFieldInsByName) && appins.setFieldInsByName(fieldName, this, customprops);
        }
    }

    /**
     * 设置组件的值
     * @param value
     * @param afterCb
     */
    setValue(value, afterCb) {
        this.compIns.setValue(value, afterCb);
    }

    /**
     * 获取组件的值
     * @return {*}
     */
    getValue() {
        return this.compIns.getValue();
    }

    focus() {
        this.compIns.focus();
    }

    /**
     * 设置“组件的值-编辑前”事件处理。重复调用此方法，可实现“多次事件绑定”
     * @param func {function(compIns: {})} // compIns 是当前编辑组件的实例
     */
    addEditBeforeHandler(func) {
        this.compIns.addEditBeforeHandler(func);
    }

    /**
     * 设置“组件的值-编辑后”事件处理。重复调用此方法，可实现“多次事件绑定”
     * @param func {function(value)}
     */
    addEditAfterHandler(func) {
        this.compIns.addEditAfterHandler(func);
    }

    /**
     * 手动触发“值变化”的事件
     */
    dispatchValueChange() {
        this.compIns.hdlValueChange(this.getValue());
    }

    /**
     * 设置 Form.Item 组件的属性。
     * 一般用于 afc 调用，实现个性化逻辑。
     * @param props {object} 属性值，例如设置 {normalize: (value, prevValue, prevValues) => {}}。更多属性参考：https://ant.design/components/form-cn/#Form.Item
     * @param afterCb
     */
    setFormItemProps(props, afterCb) {
        this.setState({formItemProps: {...this.state.formItemProps, ...props}}, afterCb);
    }

    dealValue({value, defaultValue}) {
        return {value, defaultValue}
    }

    mainRender(context) {
        let {
            style, value, defaultValue, fieldCtrl, disabled,
            compLabel, fieldName, transFieldName, labelWidth,
            formItemProps = {}, compProps = {}, cell, tooltip,
            ...restProps
        } = this.getProps();
        // const {fieldCtrl} = this.state;
        // const disabled = this.getPropsByName('disabled');
        const styleO = style || {};
        const Comp = this.Comp;

        if (false !== transFieldName && this.Comp && 'filter' === this.Comp.fieldType && restProps.componentType === ComponentType.FINDER) {
            !endsWith(fieldName, '.id') && (fieldName += '.id');
        }

        let fCompProps = {
            compLabel,
            fieldName,
            cell,
            ...restProps,
            ...compProps,
            ...this.compMoreProps,
            onRef: (ref) => {
                this.compIns = ref;
            }
        };
        const valObj = this.dealValue({value, defaultValue});
        formItemProps = {
            ...formItemProps,
            ...this.state.formItemProps
        };

        if (FieldCtrl.REQUIRED === fieldCtrl) {
            formItemProps = {
                ...formItemProps,
                rules: [
                    {required: true, message: this.myFormatMessage('comp.form.field.required', {name: compLabel})},
                    ...(formItemProps.rules || []),
                    ...(this.state.formItemProps.rules || [])
                ]
            };
        }
        if (FieldCtrl.HIDDEN === fieldCtrl) {
            // formItemProps = {...formItemProps, style: {display: 'none'}};
        }
        if (FieldCtrl.READONLY === fieldCtrl || disabled) {
            fCompProps.disabled = true;
        }

        if (isEmpty(fieldName)) {

            if ('value' in this.props) { // 受控组件
                fCompProps.value = valObj.value;
            } else if ('defaultValue' in this.props) {
                fCompProps.defaultValue = valObj.defaultValue;
            }

            if (isEmpty(compLabel)) {
                return Comp ? <Comp {...fCompProps} style={styleO}/> : null;
            }

        } else {
            formItemProps.name = fieldName;

            if ('value' in this.props) { // 受控组件
                formItemProps.initialValue = valObj.value;
            } else if ('defaultValue' in this.props) {
                formItemProps.initialValue = valObj.defaultValue;
            }
        }

        if (!isEmpty(compLabel)) {
            let labelW = parseInt(labelWidth);
            let tmpStyleO = {
                display: 'inline-block',
                width: isNaN(labelW) ? 'auto' : labelW,
                overflow: 'hidden',
                textOverflow: 'ellipsis'
            };

            // 如果是查找器，则点击左边的标签可跳转到对应的应用页
            if (fCompProps.componentType === ComponentType.FINDER) {
                compLabel = <span onClick={(e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    if (this.compIns) {
                        const $ins = this.compIns;
                        const {appCode, appins, finderCode, finderActionCustom} = $ins.getProps();
                        if (appins && appins.onFinderAction && appCode) {
                            // finderActionCustom 自定义传入的跳转属性，一般用于查找器的子分类对应需要跳转到父类对应的详情页面
                            appins.onFinderAction(!isEmpty(finderActionCustom) ? finderActionCustom : {type: 'detail', appCode, value: $ins.getValue(), finderCode});
                        }
                    }
                }} className={styles.label} style={tmpStyleO} title={compLabel}>{compLabel}</span>;
            } else {
                compLabel = (
                    <span style={tmpStyleO} title={compLabel}>
                        {compLabel}
                    </span>
                )
            }
        }

        let fItemStyle = {...pick(styleO, ['width', 'height']), ...(formItemProps.style || {})};

        let fromItemComp = (
            <Form.Item label={compLabel}
                       validateFirst={true}
                       {...formItemProps}
                       className={`field-item ${restProps.className || ''} ${styles.field || ''}`}
                       style={fItemStyle}
            >
                {
                    (true !== cell && FieldCtrl.HIDDEN === fieldCtrl) ? '*****'
                        : (Comp ? (
                            <Comp
                                {...fCompProps}
                                style={{...omit(styleO, ['width']), ...(compProps.style || {})}}
                            />
                        ) : null)
                }
            </Form.Item>
        );

        // 自定义文字提示
        let fromItemComp_toolTip = isEmpty(tooltip) && fromItemComp || <Tooltip title={tooltip}>{fromItemComp}</Tooltip>;

        return (
            this.props.colSpan && this.props.colSpan > 0 ?
                <Col span={this.props.colSpan}>{fromItemComp_toolTip}</Col> : fromItemComp_toolTip
        )
    }
}